import matplotlib.pyplot as plt
import numpy as np
from numdifftools import Gradient
from numdifftools import Hessian
from scipy.optimize import basinhopping


# Function to numerically compute the gradient of the Rosenbrock function
def rosen_der_numerical(x):
    return Gradient(rosen)(x)


# Function to numerically compute the Hessian of the Rosenbrock function
def rosen_hess_numerical(x):
    return Hessian(rosen)(x)


# Plot Iteration History
def plot_iteration_history(iteration_history):
    x_values = [iter for iter, _ in iteration_history]  # Iteration numbers as x-axis
    y_values = [val for _, val in iteration_history]  # Objective function values as y-axis

    plt.plot(x_values, y_values, 'o-', markersize=3)
    plt.xlabel('Iteration Number')
    plt.ylabel('Objective Function Value')
    plt.title('Iteration History of Basin-Hopping Algorithm')
    plt.grid(True)
    plt.show()


# Callback Function
def callback(x, f, accepted, verbose=False):
    global iter_count
    iter_count += 1
    iteration_history.append((iter_count, f))

    if verbose:
        print(f"Iteration {iter_count}: at minimum {f:.4f} accepted {int(accepted)}")


# 定义勒让德多项式
def legendre_poly(x_arr, x0):
    # x_arr是系数数组，例如x_arr = np.array([1.3, 0.7, 0.8, 1.9, 1.2]) # 初始解 对应勒让德多项式的系数 1.3为1.3*legendre(0, x)，0.7为0.7*legendre(1, x)，0.8为0.8*legendre(2, x)，1.9为1.9*legendre(3, x)，1.2为1.2*legendre(4, x)
    # 对根据这些勒让德多项式进行求和，得到它们的和函数。
    # 返回函数在x0的值
    pass

def rosen_args(legendre_poly, x_arr,a,b):
    # 对勒让德多项式进行微分算子操作例如二阶常微分操作
    # 计算它的平方在a，b范围内的积分
    pass

parr1 = -1
parr2 = 1


def rosen(x):
    return rosen_args(x, parr1, parr2)

from scipy.special import legendre

x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2]) # 初始解 对应勒让德多项式的系数 1.3为1.3*legendre(0, x)，0.7为0.7*legendre(1, x)，0.8为0.8*legendre(2, x)，1.9为1.9*legendre(3, x)，1.2为1.2*legendre(4, x)


iteration_history = []  # Reset iteration history
iter_count = 0  # Reset iteration counter

result = basinhopping(rosen, x0, minimizer_kwargs={"method": 'trust-ncg', 'jac': rosen_der_numerical,
                                                   'hess': rosen_hess_numerical},
                      niter=50, callback=lambda x, f, accepted: callback(x, f, accepted, verbose=False))
print("Trust-Exact solution:", result.x)
print("Objective function value at solution:", result.fun)

# Plot the iteration history
plot_iteration_history(iteration_history)
